﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.ComponentModel;

namespace GoodStuff.Web
{
    /// <summary>
    /// Utility class voor het omgaan met QueryStrings
    /// </summary>
    public static class QueryStringTools
    {
        /// <summary>
        /// Reads and converts querystring parameters to the correct type.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="request"></param>
        /// <param name="parameterName"></param>
        /// <param name="required"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T GetParameter<T>(this HttpRequest request, string parameterName, bool required, T defaultValue) where T : struct
        {
            string value = request.QueryString[parameterName];
            if (string.IsNullOrEmpty(value))
            {
                if (required)
                {
                    throw new QueryStringException(parameterName, "parameter is required");
                }
                else
                {
                    return defaultValue;
                }
            }

            TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
            return (T)converter.ConvertFromString(value);
        }

        /// <summary>
        /// Reads and converts querystring parameters to the correct type. If no parameter value was found,
        /// a default value will be used.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="page"></param>
        /// <param name="parameterName"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T GetParameter<T>(this Page page, string parameterName, T defaultValue) where T : struct
        {
            return GetParameter<T>(page.Request, parameterName, false, defaultValue);
        }

        /// <summary>
        /// Reads and converts querystring parameters to the correct type. If no parameter value was found,
        /// an exception is thrown.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="page"></param>
        /// <param name="parameterName"></param>
        /// <returns></returns>
        public static T GetParameter<T>(this Page page, string parameterName) where T : struct
        {
            return GetParameter<T>(page.Request, parameterName, true, default(T));
        }

        private static T GetParameter<T>(this Page page, string parameterName, bool required, T defaultValue) where T : struct
        {
            return GetParameter<T>(page.Request, parameterName, required, defaultValue);
        }

        /// <summary>
        /// Reads querystring parameters and leaves it a string.
        /// </summary>
        /// <param name="page">current Page</param>
        /// <param name="parameterName">name of the parameter</param>
        /// <param name="required">required? if required but not found, an error will be thrown</param>
        /// <returns>the value of the querystringparameter</returns>
        public static string GetParameter(this Page page, string parameterName, bool required)
        {
            return GetParameter(page.Request, parameterName, required);
        }

        /// <summary>
        /// Reads querystring parameters and leaves it a string.
        /// </summary>
        /// <param name="page">current HttpRequest</param>
        /// <param name="parameterName">name of the parameter</param>
        /// <param name="required">required? if required but not found, an error will be thrown</param>
        /// <returns>the value of the querystringparameter</returns>
        public static string GetParameter(this HttpRequest request, string parameterName, bool required)
        {
            string value = request.QueryString[parameterName];
            if (required && string.IsNullOrEmpty(value))
            {
                throw new QueryStringException(parameterName, "parameter is required");
            }
            return value;
        }
    }

    /// <summary>
    /// Exception class for QueryString failures.
    /// </summary>
    public class QueryStringException : Exception
    {
        /// <summary>
        /// Creates a new querystring exception 
        /// </summary>
        /// <param name="parameterName"></param>
        /// <param name="message"></param>
        public QueryStringException(string parameterName, string message)
            : base(message)
        {
            ParameterName = parameterName;
        }

        /// <summary>
        /// The parameter name responsible for throwing the exception.
        /// </summary>
        public string ParameterName { get; set; }

        /// <summary>
        /// Translates this exception to a readable format.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("The QueryString parameter {0} was missing or invalid", ParameterName);
        }
        
    }
}
